#!/bin/bash

set -e

initfile=/etc/rundeck.init

chmod 1777 /tmp

if [[ -n "${RUNDECK_GID}" && -n "${RUNDECK_UID}" ]]; then
  echo "Setting rundeck account to ${RUNDECK_UID}:${RUNDECK_GID}"
  groupmod -o -g ${RUNDECK_GID} rundeck
  usermod -o -u ${RUNDECK_UID} -g ${RUNDECK_GID} rundeck
fi

# chown directories and files that might be coming from volumes
find /var/lib/mysql \
  \! -user mysql -exec chown -R mysql:mysql {} \;
find /etc/rundeck /var/rundeck /var/log/rundeck \
  /var/lib/rundeck /opt/rundeck-defaults /tmp/rundeck \
  \! -user rundeck -exec chown -R rundeck:rundeck {} \;
chmod -R 750 /tmp/rundeck

# Plugins
if ls /opt/rundeck-plugins/* 1> /dev/null 2>&1; then
   echo "=>Installing plugins from /opt/rundeck-plugins"
   cp -Rf /opt/rundeck-plugins/* /var/lib/rundeck/libext/
   chown -R rundeck:rundeck /var/lib/rundeck/libext
fi

if [ ! -f "${initfile}" ]; then
   SERVER_URL=${SERVER_URL:-"https://0.0.0.0:4443"}
   SERVER_HOSTNAME=$(echo ${SERVER_URL} | awk -F/ '{print $3}' | awk -F: '{print $1}')
   SERVER_PROTO=$(echo ${SERVER_URL} | awk -F/ '{print $1}' | awk -F: '{print $1}')
   SERVER_PORT=$(echo ${SERVER_URL} | awk -F/ '{print $3}' | awk -F: '{print $2}')
   if [ -z ${SERVER_PORT} ]; then
      # No port in SERVER_URL so assume 443 for HTTPS or 80 otherwise
      if [ ${SERVER_PROTO} == "https" ]; then
         SERVER_PORT=443
      else
        SERVER_PORT=80
      fi
   fi

  # Docker secrets support
  if [ -f /run/secrets/RUNDECK_PASSWORD ]; then
    RUNDECK_PASSWORD=$(< /run/secrets/RUNDECK_PASSWORD)
  fi
  if [ -f /run/secrets/DATABASE_ADMIN_PASSWORD ]; then
    DATABASE_ADMIN_PASSWORD=$(< /run/secrets/DATABASE_ADMIN_PASSWORD)
  fi
  if [ -f /run/secrets/KEYSTORE_PASS ]; then
    KEYSTORE_PASS=$(< /run/secrets/KEYSTORE_PASS)
  fi
  if [ -f /run/secrets/TRUSTSTORE_PASS ]; then
    TRUSTSTORE_PASS=$(< /run/secrets/TRUSTSTORE_PASS)
  fi
  if [ -f /run/secrets/RUNDECK_ADMIN_PASSWORD ]; then
    RUNDECK_ADMIN_PASSWORD=$(< /run/secrets/RUNDECK_ADMIN_PASSWORD)
  fi
  if [ -f /run/secrets/RUNDECK_STORAGE_PASSWORD ]; then
    RUNDECK_STORAGE_PASSWORD=$(< /run/secrets/RUNDECK_STORAGE_PASSWORD)
  fi

   DATABASE_URL=${DATABASE_URL:-"jdbc:mysql://localhost/rundeckdb?autoReconnect=true"}
   DATABASE_DRIVER=${DATABASE_DRIVER:-"org.mariadb.jdbc.Driver"}
   RUNDECK_USER=${RUNDECK_USER:-"rundeck"}
   RUNDECK_PASSWORD=${RUNDECK_PASSWORD:-$(pwgen -s 15 1)}
   DATABASE_ADMIN_PASSWORD=${DATABASE_ADMIN_PASSWORD:-${RUNDECK_PASSWORD}}
   DATABASE_ADMIN_USER=${DATABASE_ADMIN_USER:-rundeck}
   RUNDECK_STORAGE_PROVIDER=${RUNDECK_STORAGE_PROVIDER:-"db"}
   NO_LOCAL_MYSQL=${NO_LOCAL_MYSQL:-"false"}
   SKIP_DATABASE_SETUP=${SKIP_DATABASE_SETUP:-"false"}
   LOGIN_MODULE=${LOGIN_MODULE:-"RDpropertyfilelogin"}
   JAAS_CONF_FILE=${JAAS_CONF_FILE:-"jaas-loginmodule.conf"}
   KEYSTORE_PASS=${KEYSTORE_PASS:-"adminadmin"}
   TRUSTSTORE_PASS=${TRUSTSTORE_PASS:-${KEYSTORE_PASS}}
   CLUSTER_MODE=${CLUSTER_MODE:-"false"}

   update_user_password () {
      (
      echo "UPDATE mysql.user SET password=PASSWORD('${2}') WHERE user='${1}';"
      echo "FLUSH PRIVILEGES;"
      echo "quit"
      ) |
      mysql
   }

   echo "=>Initializing rundeck - This may take a few minutes"
   if [ ! -f /var/lib/rundeck/.ssh/id_rsa ]; then
       echo "=>Generating rundeck key"
       sudo -u rundeck ssh-keygen -t rsa -b 4096 -f /var/lib/rundeck/.ssh/id_rsa -N ''
   fi


   # copy rundeck defaults
   if [ ! "$(ls -1A /etc/rundeck|grep -v lost+found)" ]; then
      cp -R /opt/rundeck-defaults/* /etc/rundeck
      chown -R rundeck:rundeck /etc/rundeck
   fi

   if [ ! -f /etc/rundeck/ssl/truststore ]; then
       echo "=>Generating ssl cert"
       sudo -u rundeck mkdir -p /etc/rundeck/ssl
       if [ ! -f /etc/rundeck/ssl/keystore ]; then
           sudo -u rundeck keytool -importkeystore -destkeystore /etc/rundeck/ssl/keystore -srckeystore /etc/ssl/certs/java/cacerts -deststoretype JKS -srcstoretype JKS -deststorepass ${TRUSTSTORE_PASS} -srcstorepass changeit -noprompt > /dev/null
       fi
       sudo -u rundeck keytool -keystore /etc/rundeck/ssl/keystore -alias rundeck -genkey -keyalg RSA -keypass ${KEYSTORE_PASS} -storepass ${TRUSTSTORE_PASS} -dname "cn=localhost, o=OME, c=DE"
       cp /etc/rundeck/ssl/keystore /etc/rundeck/ssl/truststore
   fi

   if [ "${NO_LOCAL_MYSQL}" == "false" ]; then
      echo "=>Initializing local MySQL..."
      if [ "$(ls -A1 /var/lib/mysql|grep -v lost+found)" ]; then
         service mariadb start
      else
         echo "=>MySQL datadir is empty...initializing"
         /usr/bin/mysql_install_db --user=mysql --basedir=/usr --datadir=/var/lib/mysql
         service mariadb start
     fi

     (
     echo "CREATE DATABASE IF NOT EXISTS rundeckdb;"
     echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE, CREATE VIEW, ALTER, INDEX, EXECUTE ON rundeckdb.* TO '${RUNDECK_USER}'@'localhost' IDENTIFIED BY '${RUNDECK_PASSWORD}';"
     echo "quit"
     ) |
     mysql
     sleep 5
     service mariadb stop
     # Add MySQL to supervisord conf
     cat /opt/mariadb.conf >> /etc/supervisor/conf.d/rundeck.conf
   else
      echo "=>NO_LOCAL_MYSQL set to true.  Skipping local MySQL setup"
      if [[ "${DATABASE_URL}" == *"mysql"* && "${SKIP_DATABASE_SETUP}" != "true" ]]; then
        MYSQL_CNX_STRING=$(echo ${DATABASE_URL} | grep -oP "(?<=jdbc:mysql:\/\/)(.*)(?=\/)")
        MYSQL_SERVER_NODE=${MYSQL_CNX_STRING}
        MYSQL_SERVER_PORT=3306
        echo ${MYSQL_CNX_STRING} | grep -q ':' && {
         MYSQL_SERVER_NODE=$(echo ${MYSQL_CNX_STRING}|awk -F':' '{print $1}')
         MYSQL_SERVER_PORT=$(echo ${MYSQL_CNX_STRING}|awk -F':' '{print $2}')
            }
            echo "=>Initializing remote MySQL setup"
            (
             echo "CREATE DATABASE IF NOT EXISTS rundeckdb;"
             echo "GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE, CREATE VIEW, ALTER, INDEX, EXECUTE ON rundeckdb.* TO '${RUNDECK_USER}'@'%' IDENTIFIED BY '${RUNDECK_PASSWORD}';"
             echo "quit"
             ) |
         mysql --host=${MYSQL_SERVER_NODE} --port=${MYSQL_SERVER_PORT} --user=${DATABASE_ADMIN_USER} --password=${DATABASE_ADMIN_PASSWORD}
      elif [[ "${DATABASE_URL}" == *"postgresql"* && "${SKIP_DATABASE_SETUP}" != "true" ]]; then
        DATABASE_DRIVER="org.postgresql.Driver"
        PSQL_CNX_STRING=$(echo ${DATABASE_URL} | grep -oP "(?<=jdbc:postgresql:\/\/)(.*)(?=\/)")
        PSQL_SERVER_NODE=${PSQL_CNX_STRING}
        PSQL_SERVER_PORT=5432
        echo ${PSQL_CNX_STRING} | grep -q ':' && {
            PSQL_SERVER_NODE=$(echo ${PSQL_CNX_STRING}|awk -F':' '{print $1}')
            PSQL_SERVER_PORT=$(echo ${PSQL_CNX_STRING}|awk -F':' '{print $2}')
        }

        # Extract database from database url
        URL_SPLIT=(`echo ${DATABASE_URL} | tr '/' ' '`)
        PSQL_DATABASE=$(echo "${URL_SPLIT[${#URL_SPLIT[@]}-1]}")

        echo "Connecting to postgres server hostname ${PSQL_SERVER_NODE}"
        echo "Connecting to postgres server port ${PSQL_SERVER_PORT}"
        echo "Postgres database ${PSQL_DATABASE}"
        export PGPASSWORD=${DATABASE_ADMIN_PASSWORD}
        echo "=>Initializing remote Postgres setup"
        (
           echo "CREATE DATABASE ${PSQL_DATABASE};"
        ) |
        psql --host ${PSQL_SERVER_NODE} --port ${PSQL_SERVER_PORT} --username ${DATABASE_ADMIN_USER} --dbname postgres
      else
        echo "=>Skipping remote database setup"
      fi
   fi

  if ! [ -z "${EXTERNAL_SERVER_URL}" ]; then
    # if external_server_url is specified, write it in
    sed -i 's,#\?grails.serverURL\=.*,grails.serverURL\='${EXTERNAL_SERVER_URL}',g' /etc/rundeck/rundeck-config.properties
  fi

   sed -i 's,dataSource.dbCreate.*,,g' /etc/rundeck/rundeck-config.properties
   sed -i 's,dataSource.url = .*,dataSource.url = '${DATABASE_URL//\&/\\\&}',g' /etc/rundeck/rundeck-config.properties
   if grep -q dataSource.driverClassName /etc/rundeck/rundeck-config.properties ; then
      sed -i 's,dataSource.driverClassName = .*,dataSource.driverClassName = '${DATABASE_DRIVER}',g' /etc/rundeck/rundeck-config.properties
   else
      echo -e "\ndataSource.driverClassName = ${DATABASE_DRIVER}" >> /etc/rundeck/rundeck-config.properties
   fi
   if grep -q dataSource.username /etc/rundeck/rundeck-config.properties ; then
      :
   else
      echo -e "\ndataSource.username = ${RUNDECK_USER}" >> /etc/rundeck/rundeck-config.properties
   fi
   if grep -q dataSource.password /etc/rundeck/rundeck-config.properties ; then
      sed -i 's,dataSource.password = .*,dataSource.password = '${RUNDECK_PASSWORD}',g' /etc/rundeck/rundeck-config.properties
   else
      echo -e "\ndataSource.password = ${RUNDECK_PASSWORD}" >> /etc/rundeck/rundeck-config.properties
   fi

   # Check if we need to set the rundeck.gui.brand.html property
   if [ -n "${GUI_BRAND_HTML}" ]; then
      if grep -q rundeck.gui.brand.html /etc/rundeck/rundeck-config.properties ; then
        sed -i 's/rundeck\.gui\.brand\.html.*$/rundeck\.gui\.brand\.html = '${GUI_BRAND_HTML}'/g' /etc/rundeck/rundeck-config.properties
      else
        echo "rundeck.gui.brand.html = ${GUI_BRAND_HTML}" >> /etc/rundeck/rundeck-config.properties
      fi
   fi

   # Check if we need to set the grails.mail.host property
   if [ -n "${SMTP_HOST}" ]; then
      if grep -q grails.mail.host /etc/rundeck/rundeck-config.properties ; then
        sed -i 's/grails\.mail\.host.*$/grails\.mail\.host = '${SMTP_HOST}'/g' /etc/rundeck/rundeck-config.properties
      else
        echo "grails.mail.host = ${SMTP_HOST}" >> /etc/rundeck/rundeck-config.properties
      fi
   fi

   # Check if we need to set the grails.mail.port property
   if [ -n "${SMTP_PORT}" ]; then
      if grep -q grails.mail.port /etc/rundeck/rundeck-config.properties ; then
        sed -i 's/grails\.mail\.port.*$/grails\.mail\.port = '${SMTP_PORT}'/g' /etc/rundeck/rundeck-config.properties
      else
        echo "grails.mail.port = ${SMTP_PORT}" >> /etc/rundeck/rundeck-config.properties
      fi
   fi

   # Check if we need to set the grails.mail.username property
   if [ -n "${SMTP_USERNAME}" ]; then
      if grep -q grails.mail.username /etc/rundeck/rundeck-config.properties ; then
        sed -i 's/grails\.mail\.username.*$/grails\.mail\.username = '${SMTP_USERNAME}'/g' /etc/rundeck/rundeck-config.properties
      else
        echo "grails.mail.username = ${SMTP_USERNAME}" >> /etc/rundeck/rundeck-config.properties
      fi
   fi

   # Check if we need to set the grails.mail.password property
   if [ -n "${SMTP_PASSWORD}" ]; then
      if grep -q grails.mail.password /etc/rundeck/rundeck-config.properties ; then
        sed -i 's/grails\.mail\.password.*$/grails\.mail\.password = '${SMTP_PASSWORD}'/g' /etc/rundeck/rundeck-config.properties
      else
        echo "grails.mail.password = ${SMTP_PASSWORD}" >> /etc/rundeck/rundeck-config.properties
      fi
   fi

   # Check if we need to set the grails.mail.default.from property
   if [ -n "${SMTP_DEFAULT_FROM}" ]; then
      if grep -q grails.mail.default.from /etc/rundeck/rundeck-config.properties ; then
        sed -i 's/grails\.mail\.default\.from.*$/grails\.mail\.default\.from = '${SMTP_DEFAULT_FROM}'/g' /etc/rundeck/rundeck-config.properties
      else
        echo "grails.mail.default.from = ${SMTP_DEFAULT_FROM}" >> /etc/rundeck/rundeck-config.properties
      fi
   fi

   # Check if we need to set the quartz.threadPool.threadCount property
   if [ -n "${RUNDECK_THREAD_COUNT}" ]; then
      if grep -q quartz.threadPool.threadCount /etc/rundeck/rundeck-config.properties ; then
        sed -i 's/quartz\.threadPool\.threadCount.*$/quartz\.threadPool\.threadCount = '${RUNDECK_THREAD_COUNT}'/g' /etc/rundeck/rundeck-config.properties
      else
        echo "quartz.threadPool.threadCount = ${RUNDECK_THREAD_COUNT}" >> /etc/rundeck/rundeck-config.properties
      fi
   fi

   # framework.properties
   sed -i 's,framework.server.name\ \=.*,framework.server.name\ \=\ '${SERVER_HOSTNAME}',g' /etc/rundeck/framework.properties
   sed -i 's,framework.server.hostname\ \=.*,framework.server.hostname\ \=\ '${SERVER_HOSTNAME}',g' /etc/rundeck/framework.properties
   sed -i 's,framework.server.port\ \=.*,framework.server.port\ \=\ '${SERVER_PORT}',g' /etc/rundeck/framework.properties
   sed -i 's,framework.server.url\ \=.*,framework.server.url\ \=\ '${SERVER_URL}',g' /etc/rundeck/framework.properties
   if [ -n "${RUNDECK_SERVER_UUID}" ]; then
      if grep -q rundeck.server.uuid /etc/rundeck/framework.properties ; then
        sed -i 's/rundeck\.server\.uuid.*$/rundeck\.server\.uuid = '${RUNDECK_SERVER_UUID}'/g' /etc/rundeck/framework.properties
      else
        echo "quartz.threadPool.threadCount = ${RUNDECK_THREAD_COUNT}" >> /etc/rundeck/rundeck-config.properties
      fi
   fi

   # if the admin pwd is still the default password and RUNDECK_ADMIN_PASSWORD is defined
   if $(grep --silent '^admin:admin,' /etc/rundeck/realm.properties) && [[ -n "${RUNDECK_ADMIN_PASSWORD}" ]]; then
      sed -i 's*^admin:admin,*admin:'${RUNDECK_ADMIN_PASSWORD}',*g' /etc/rundeck/realm.properties
      # If EXTERNAL_SERVER_URL is being used, the inside/outside ports for rundeck confuse the standard
      # CLI tools like rd-jobs, rd-project and they won't work.  You will need to use the new and improved
      # rundeck-cli tools.  To make the new CLI tools easier to use, go ahead and add an API token for the
      # admin account as a hash of the admin password.
      if [[ -n "${EXTERNAL_SERVER_URL}" ]]; then
        grep --silent "rundeck\.tokens\.file" /etc/rundeck/framework.properties || \
          echo "rundeck.tokens.file=/etc/rundeck/tokens.properties" >> /etc/rundeck/framework.properties
        mytoken=$(printf '%s' "${RUNDECK_ADMIN_PASSWORD}" | md5sum | cut -d ' ' -f 1)
        [[ -e /etc/rundeck/tokens.properties ]] \
          && grep --silent "^admin:" /etc/rundeck/tokens.properties \
          && sed -i -e "s,^admin:.*,admin: ${mytoken},g" /etc/rundeck/tokens.properties \
          || echo "admin: ${mytoken}" >> /etc/rundeck/tokens.properties
        chown rundeck:rundeck /etc/rundeck/tokens.properties
      fi
   fi

   if [ "${RUNDECK_STORAGE_PROVIDER}" == "db" ]; then
      if grep -q rundeck.storage.provider.1.type /etc/rundeck/rundeck-config.properties ; then
        sed -i 's/rundeck\.storage\.provider\.1\.type.*$/rundeck\.storage\.provider\.1\.type='${RUNDECK_STORAGE_PROVIDER}'/g' /etc/rundeck/rundeck-config.properties
      else
        echo "rundeck.storage.provider.1.type=db" >> /etc/rundeck/rundeck-config.properties
      fi
      if grep -q rundeck.config.storage.converter.1.path /etc/rundeck/rundeck-config.properties ; then
        :
      else
        echo "rundeck.config.storage.converter.1.path=/" >> /etc/rundeck/rundeck-config.properties
      fi
      if ! [ -z "${RUNDECK_STORAGE_PASSWORD}" ]; then
        if grep -q rundeck.storage.converter.1.config.password /etc/rundeck/rundeck-config.properties ; then
          sed -i 's/rundeck\.storage\.converter\.1\.config\.password.*$/rundeck\.storage\.converter\.1\.config\.password='${RUNDECK_STORAGE_PASSWORD}'/g' /etc/rundeck/rundeck-config.properties
        else
          echo "rundeck.storage.converter.1.config.password=${RUNDECK_STORAGE_PASSWORD}" >> /etc/rundeck/rundeck-config.properties
        fi
        if grep -q rundeck.config.storage.converter.1.config.password /etc/rundeck/rundeck-config.properties ; then
          sed -i 's/rundeck\.config\.storage\.converter\.1\.config\.password.*$/rundeck\.config\.storage\.converter\.1\.config\.password='${RUNDECK_STORAGE_PASSWORD}'/g' /etc/rundeck/rundeck-config.properties
        else
          echo "rundeck.config.storage.converter.1.config.password=${RUNDECK_STORAGE_PASSWORD}" >> /etc/rundeck/rundeck-config.properties
        fi
      fi
   fi

   if [ -n "${RUNDECK_SERVER_UUID}" ]; then
      if grep -q rundeck.server.uuid /etc/rundeck/framework.properties ; then
        sed -i 's,rundeck.server.uuid \=.*,rundeck.server.uuid \= '${RUNDECK_SERVER_UUID}',g' /etc/rundeck/framework.properties
      else
        echo "rundeck.server.uuid = ${RUNDECK_SERVER_UUID}" >> /etc/rundeck/framework.properties
      fi
   fi

   if [ "${CLUSTER_MODE}" == "true" ]; then
      echo "rundeck.clusterMode.enabled=true" >> /etc/rundeck/rundeck-config.properties
      sed -i 's,rundeck.server.uuid \=.*,rundeck.server.uuid \= '$(uuidgen)',g' /etc/rundeck/framework.properties
   fi

   sed -i 's,JAAS_CONF\=.*,JAAS_CONF\="/etc/rundeck/'${JAAS_CONF_FILE}'",' /etc/rundeck/profile
   sed -i 's,LOGIN_MODULE\=.*,LOGIN_MODULE\="'${LOGIN_MODULE}'",' /etc/rundeck/profile
   sed -i 's,keystore\.password\=.*,keystore\.password\='${KEYSTORE_PASS}',' /etc/rundeck/ssl/ssl.properties
   sed -i 's,key\.password\=.*,key\.password\='${TRUSTSTORE_PASS}',' /etc/rundeck/ssl/ssl.properties
   sed -i 's,truststore\.password\=.*,truststore\.password\='${TRUSTSTORE_PASS}',' /etc/rundeck/ssl/ssl.properties

   # Generate the system wide locales in the background.
   # It may take a long time, depending on the mounted /etc/locale.gen.
   locale-gen &

   echo -e "\n\n\n"
   echo "==================================================================="
   if [ "${NO_LOCAL_MYSQL}" == "true" ]; then
      echo "NO_LOCAL_MYSQL set to true so local MySQL has not been configured or started"
   else
      echo "MySQL user 'root' has no password but only allows local connections"
   fi
   echo "MySQL user '${RUNDECK_USER}' password set to ${RUNDECK_PASSWORD}"
   echo "Rundeck Storage provider set to ${RUNDECK_STORAGE_PROVIDER}"
   echo "Rundeck public key:"
   cat /var/lib/rundeck/.ssh/id_rsa.pub
   if ! [ -z "${EXTERNAL_SERVER_URL}" ]; then
      echo "Server URL set to ${EXTERNAL_SERVER_URL}"
   else
      echo "Server URL set to ${SERVER_URL}"
   fi

   echo "==================================================================="

   touch ${initfile}
fi

echo -e "\n"
echo "Starting Supervisor..."
echo "It can take anywhere from 30 seconds up to a few minutes for the UI"
echo "to become available depending on your container/host VM resources."
echo "All further output is stdout/stderr from the supervisor process."
echo -e "\n"

/usr/bin/supervisord -c /etc/supervisor/supervisord.conf -n &
trap "supervisorctl shutdown && wait" SIGTERM
wait
